package edu.nf.aop;

import edu.nf.aop.annotation.Aspect;
import edu.nf.aop.proxy.CglibAopProxy;
import edu.nf.aop.proxy.JdkAopProxy;

import java.lang.reflect.Method;

/**
 * @author wangl
 * @date 2021/9/24
 * 代理工厂策略上下文
 */
public class ProxyFactory {

	/**
	 * 目标对象Class
	 */
	private final Class<?> targetClass;

	/**
	 * 代理构建处理器实例(JDK代理或者是CGLIB代理)
	 */
	private final AopProxy aopProxy;

	public ProxyFactory(Class<?> targetClass) {
		this.targetClass = targetClass;
		aopProxy = initCglibAopProxy();
	}

	public ProxyFactory(Class<?> targetClass, Class<?>[] interfaces) {
		this.targetClass = targetClass;
		aopProxy = initJdkAopProxy(interfaces);
	}

	/**
	 * 初始化CglibAopProxy
	 */
	private AopProxy initCglibAopProxy() {
		if(isAnnotationPresent()){
			return new CglibAopProxy();
		}
		throw new RuntimeException("Invalid target object.");
	}

	/**
	 * 初始化JdkAopProxy
	 */
	private AopProxy initJdkAopProxy(Class<?>[] interfaces) {
		if(isAnnotationPresent()){
			return new JdkAopProxy(interfaces);
		}
		throw new RuntimeException("Invalid target object.");
	}

	/**
	 * 检查类上或者方法上是否定义了拦截器注解
	 */
	private boolean isAnnotationPresent() {
		if(targetClass.isAnnotationPresent(Aspect.class)) {
			return true;
		}
		for (Method method : targetClass.getMethods()) {
			if (method.isAnnotationPresent(Aspect.class)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 创建代理对象
	 */
	@SuppressWarnings("unchecked")
	public <T> T createProxy() {
		return (T)aopProxy.createProxy(targetClass);
	}
}
